# -*- coding:binary -*-
require 'spec_helper'

RSpec.describe Msf::Exploit::Git::PktLine do

  let(:data) do
    "want #{Digest::SHA1.hexdigest(Rex::Text.rand_text_alpha(5..12))}"
  end

  let(:test_data) do
    Rex::Text.rand_text_alpha(8..30)
  end

  let(:test_pkt_line) do
    Msf::Exploit::Git::PktLine.generate_pkt_line(test_data)
  end

  describe '::generate_pkt_line' do
    context 'when only the first argument is supplied' do
      it 'should return a data pkt-line' do
        expected_len = data.length + 4 + 1
        len_str = expected_len.to_s(16).rjust(4, '0')
        data_pkt = Msf::Exploit::Git::PktLine.generate_pkt_line(data)

        expect(data_pkt.length).to eql(expected_len)
        expect(data_pkt).to eq("#{len_str}#{data}\n")
      end
    end

    context 'when no data is supplied' do
      it 'should return nil' do
        bad_pkt = Msf::Exploit::Git::PktLine.generate_pkt_line(nil)

        expect(bad_pkt).to eql(nil)
      end
    end

    context 'when the flush-pkt type is supplied' do
      it 'should return a flush-pkt' do
        flush_pkt = Msf::Exploit::Git::PktLine.generate_pkt_line(nil, type: 'flush-pkt')

        expect(flush_pkt).to eql('0000')
      end
    end
  end

  describe '::generate_data_pkt' do
    context 'when a string is supplied' do
      it 'should return a valid data-pkt' do
        valid_data_pkt = Msf::Exploit::Git::PktLine.generate_data_pkt(data)
        data_pkt_len = valid_data_pkt.length
        len_str = data_pkt_len.to_s(16).rjust(4, '0')

        expect(valid_data_pkt).to start_with(len_str)
        expect(valid_data_pkt).to end_with("\n")
      end
    end

    context 'when nil is supplied' do
      it 'should return nil' do
        bad_data_pkt = Msf::Exploit::Git::PktLine.generate_data_pkt(nil)

        expect(bad_data_pkt).to eql(nil)
      end
    end
  end

  describe '::get_pkt_line_data' do
    context 'when a pkt-line string is supplied' do
      it 'should return the pkt-line data' do
        result_data = Msf::Exploit::Git::PktLine.get_pkt_line_data(test_pkt_line)

        expect(result_data).to eql(test_data)
      end
    end

    context 'when data of another type is supplied' do
      it 'should return an empty string' do
        not_a_pkt_line = [ 'some data' ]
        result = Msf::Exploit::Git::PktLine.get_pkt_line_data(not_a_pkt_line)

        expect(result).to eql('')
      end
    end
  end
end
